package middle_man;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.concurrent.LinkedBlockingQueue;

public class ClientHandler extends Thread {
	private int clientID;
	private Socket clientSocket;
	private PrintWriter out;
	private BufferedReader in;
	private LinkedBlockingQueue<Request> Queue;
	private long startProcessing, stopProcessing;
	public boolean shouldSleep = false;
	private String db_host;
	
	public ClientHandler(LinkedBlockingQueue<Request> _Queue, int _clientID, Socket _clientSocket) {
		clientID = _clientID;
		clientSocket = _clientSocket;
		Queue = _Queue;
		try {
			out = new PrintWriter(clientSocket.getOutputStream(), true);
			in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
		} catch (IOException e) {
			System.err.println("Client Handler " + clientID + ": Could not create input/output streams");
			e.printStackTrace();
		}
	}
	
	public Socket getClientSocket() {
		return clientSocket;
	}
	
	public void setQueryProcessingData(long start, long stop, String host) {
		startProcessing = start;
		stopProcessing = stop;
		db_host = host;
	}
	
	public void run() {
		this.setName("MiddleMan - ClientHandler for " + clientID);
		String fromClient;
		
		System.err.println("Client Handler for " + clientID + " running...");
		try {
			while ((fromClient = in.readLine()) != null) {
				if (fromClient != null) {
					fromClient = fromClient.replaceAll("NEWLINE", "\n");
					boolean success;
					Request r = new Request(clientID, fromClient, out, this);
					// Find a queue which will accept this request
					do {
						//LinkedBlockingQueue<Request> q = sq.getRoundRobinQueue();
						//LinkedBlockingQueue<Request> q = sq.getRandomQueue();
						success = Queue.offer(r);
						if(success == false) {
							Thread.sleep(10);
						}
					} while(success == false);
			    }
				synchronized(this) {
					shouldSleep = true;
					while(shouldSleep) {
						this.wait();
					}
				}
				out.println("PROCESSING;" + db_host + ";" + startProcessing + ";" + stopProcessing);
				//
				//this.n
			}
		} catch (IOException e) {
			System.err.println("GOT AN ERROR WHILE READING/WRITING with client " + clientID);
			e.printStackTrace();
		} catch (InterruptedException e) {
			System.err.println("GOT AN ERROR WHILE COMPUTING for client " + clientID);
			e.printStackTrace();
		}
		finally {
			out.close();
			try {
				clientSocket.close();
				in.close();
			} catch (IOException e) {
				System.err.println("Client Handler for " + clientID + ": input/ouput could not be closed.");
				e.printStackTrace();
			}
			System.err.println("Clients Handler for " + clientID + " shut down.");
		}
	}
	
}
